/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package analiseSintatica.Regras.Declaracoes;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.*;
import analiseSintatica.Regras.DeclaracoesIniciais.RegraDeclaracao;
import analiseSintatica.estruturadados.ErroSintatico;
import analiseSintatica.estruturadados.NoArvore;
import java.util.LinkedList;

/**
 *
 * @author Nathy
 */
public class RegraDeclaracaoStruct extends Regra{


    protected static Regra instancia;
    protected static String estrutura = "<declaracao_struct> ::= identificador " +
            "( [*] identificador | identificador {[ numeroInteiro ]}+ ) {, ( [*]" +
            " identificador | identificador {[ numeroInteiro ]}+ )  } ;";


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraDeclaracaoStruct() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraDeclaracaoStruct getInstance() {
        if (instancia == null) {
            instancia = new RegraDeclaracaoStruct();
        }
        return (RegraDeclaracaoStruct) instancia;
    }


    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        System.out.println("Entrei aki");

        ErroSintaticoException erros = new ErroSintaticoException();

        NoArvore naoterminalDeclaracaoStruct = new NoArvore("<declaracao_struct>", false);
        int cont = 0;
        try{
        naoterminalDeclaracaoStruct.adicionaFilho(reconheceToken(listaTokens,"identificador",estrutura));
        }
        catch(ErroSintaticoException e){
            while (e.size() != 0) {
               erros.addErros(e.getErros());
            }
        }

        while(cont <= 0 || listaTokens.getFirst().getLexema().equals(",")){
            //Para repetir somente se houver uma virgula
        if(cont ==1 && listaTokens.getFirst().getLexema().equals(",") ){
         try{
             naoterminalDeclaracaoStruct.adicionaFilho(reconheceLexema(listaTokens,"delimitador", ",",estrutura));
            }
            catch(ErroSintaticoException e){
             while (e.size() != 0) {
               erros.addErros(e.getErros());
            }
            }
        }
        if(listaTokens.getFirst().getLexema().equals("*")){
            naoterminalDeclaracaoStruct.adicionaFilho(reconheceLexema(listaTokens, listaTokens.getFirst().getToken(), "*",estrutura));
        try{
            naoterminalDeclaracaoStruct.adicionaFilho(reconheceToken(listaTokens,"identificador",estrutura));
        }
        catch(ErroSintaticoException e){
            while (e.size() != 0) {
               erros.addErros(e.getErros());
            }
        }
        }

        else {
        try{
            naoterminalDeclaracaoStruct.adicionaFilho(reconheceToken(listaTokens,"identificador",estrutura));
        }
        catch(ErroSintaticoException e){
            while (e.size() != 0) {
               erros.addErros(e.getErros());
            }
        }
        //Como tem que ter pelo menos 1:
        do{
            try{
             naoterminalDeclaracaoStruct.adicionaFilho(reconheceLexema(listaTokens,"delimitador", "[",estrutura));
            }
            catch(ErroSintaticoException e){
            ErroSintatico erro = e.getErros();
            erro.setCorreto(estrutura);
            erros.addErros(erro);
            LinkedList<String> sincronizacao = new LinkedList<String>();
            sincronizacao.add("]");
            sincronizacao.add("[");
            sincronizacao.add("numeroInteiro");
            sincronizacao.add(",");
            sincronizacao.add(";");
            while (!listaContem(sincronizacao, listaTokens.getFirst())) {
                erros.addErros("Token " + listaTokens.getFirst().getToken() + " nao permitido", estrutura, listaTokens.getFirst().getLinha());
                listaTokens.removeFirst();
            }
            if (listaTokens.getFirst().getToken().equals("delimitador") && listaTokens.getFirst().getLexema().equals("[")) {
                listaTokens.removeFirst();
            }
            }

            try{
             naoterminalDeclaracaoStruct.adicionaFilho(reconheceToken(listaTokens,"numeroInteiro",estrutura));
            }
            catch(ErroSintaticoException e){
             while (e.size() != 0) {
               erros.addErros(e.getErros());
            }
            }

            try{
             naoterminalDeclaracaoStruct.adicionaFilho(reconheceLexema(listaTokens,"delimitador", "]",estrutura));
            }
            catch(ErroSintaticoException e){
            ErroSintatico erro = e.getErros();
            erro.setCorreto(estrutura);
            erros.addErros(erro);
            LinkedList<String> sincronizacao = new LinkedList<String>();
            sincronizacao.add("]");
            sincronizacao.add("[");
            sincronizacao.add(",");
            sincronizacao.add(";");
            while (!listaContem(sincronizacao, listaTokens.getFirst())) {
                erros.addErros("Token " + listaTokens.getFirst().getToken() + " nao permitido", estrutura, listaTokens.getFirst().getLinha());
                listaTokens.removeFirst();
            }
            if (listaTokens.getFirst().getToken().equals("delimitador") && listaTokens.getFirst().getLexema().equals("]")) {
                listaTokens.removeFirst();
            }
            }

        }while(listaTokens.getFirst().getLexema().equals("["));

        }
         cont = 1;
       }

        try{
           naoterminalDeclaracaoStruct.adicionaFilho(reconheceLexema(listaTokens,"delimitador", ";",estrutura));
        }
        catch(ErroSintaticoException e){
            System.out.println("n tem;");
            ErroSintatico erro = e.getErros();
            erro.setCorreto(estrutura);
            erros.addErros(erro);
            LinkedList<String> sincronizacao = RegraDeclaracaoStruct.getInstance().getSeguinte();
            while (!listaContem(sincronizacao, listaTokens.getFirst())) {
                erros.addErros("Token " + listaTokens.getFirst().getToken() + " nao permitido", estrutura, listaTokens.getFirst().getLinha());
                listaTokens.removeFirst();
            }
            if (listaTokens.getFirst().getToken().equals("delimitador") && listaTokens.getFirst().getLexema().equals(";")) {
                listaTokens.removeFirst();
            }
        }


        return naoterminalDeclaracaoStruct;
    }

    
    @Override
    protected void setPrimeiro() {
        //P<declaracao_struct> = identificador
        this.primeiro.add("identificador");
    }

    @Override
    protected void setSeguinte() {
        //S<declaracao_struct> = S<declaracao>
        this.seguinte = RegraDeclaracao.getInstance().getSeguinte();
    }

}
